package com.atguigu.hdfs.demo;

import com.atguigu.hdfs.utils.HDFSClientUtil;
import com.atguigu.hdfs.utils.RCloseUtil;
import lombok.extern.slf4j.Slf4j;
import org.apache.hadoop.conf.Configuration;
import org.apache.hadoop.fs.*;
import org.junit.jupiter.api.Test;

import java.io.IOException;
import java.net.URI;
import java.net.URISyntaxException;
import java.util.Arrays;

/**
 * @version V1.0
 * @author: guangcheng
 * @date: 2021/11/12 16:28
 * @description:
 */
@Slf4j
public class HDFSClient {
    //Hadoop集群内部的通信地址
    private static String nameNodeUrl = "hdfs://node1:8020";
    private static String user = "atguigu";

    @Test
    public void test() {
        FileSystem fsOp = null;

        try {
            URI uri = new URI(nameNodeUrl);
            //获取客户端操作对象
            fsOp = FileSystem.get(uri, new Configuration(), user);

            boolean flag = fsOp.mkdirs(new Path("/xiyou/glz"));
            log.info("创建结果 {}", flag);


            log.info("hello hdfs");
        } catch (URISyntaxException e) {
            log.info("{}", e.getMessage());
        } catch (IOException e) {
            log.info("{}", e.getMessage());
        } catch (InterruptedException e) {
            log.info("{}", e.getMessage());
        } finally {
            RCloseUtil.close(fsOp);
        }


    }


    /**
     * 创建目录
     *
     * @throws IOException
     */
    @Test
    public void hdfsDemo() throws IOException {
        FileSystem fsOp = HDFSClientUtil.getHDFSClientInstance(nameNodeUrl, user);

        if (fsOp != null) {

            boolean mkdirs = fsOp.mkdirs(new Path("/xiyou/psd"));
            log.info("[**^O^^O^ result= {} ^O^^O^**]", mkdirs);
            RCloseUtil.close(fsOp);
        }
    }


    /**
     * 上传文件
     */
    @Test
    public void testPutFile() throws IOException {

        FileSystem fsOp = HDFSClientUtil.getHDFSClientInstance(nameNodeUrl, user);

        if (fsOp != null) {

            /**
             * delSrc: 是否删除本地文件, 在上传结束后
             * overwrite: 是否覆盖集群中存在的文件
             * src: 本地文件来源
             * dst: hadoop 集群目录
             *
             * hdfs://node1:8020/xiyou/psd <=> /xiyou/psd  两种写法等价
             */
            fsOp.copyFromLocalFile(false,
                    true,
                    new Path("C:\\Users\\ZZGGC\\Pictures\\001DDXzsgy1gul1v38v92j60u011i0xh02.jpg"),
                    new Path("hdfs://node1:8020/xiyou/psd"));

            RCloseUtil.close(fsOp);
        }

    }


    /**
     * D:\testarea\bigdatatest\hadoop\hdfs\ts.txt
     *
     *     <property>
     *         <name>dfs.replication</name>
     *         <value>2</value>
     *     </property>
     *
     *     default => def => client project resources xxx.xml => 代码配置  (优先级变高)
     */
    @Test
    public void testConfigPriority() throws IOException {
        FileSystem fsOp = HDFSClientUtil.getHDFSClientInstance(nameNodeUrl, user);

        if (fsOp != null) {

            fsOp.copyFromLocalFile(true,
                    true,
                    new Path("D:\\testarea\\bigdatatest\\hadoop\\hdfs\\ts.txt"),
                    new Path("hdfs://node1:8020/xiyou"));

            RCloseUtil.close(fsOp);
        }
    }


    /**
     * 自定义配置, 用编码方式实现
     * default => def => client project resources xxx.xml => 代码配置  (优先级变高)
     *
     * @throws IOException
     */
    @Test
    public void testDefConfPutFile() throws IOException {

        Configuration conf = new Configuration();
        conf.set("dfs.replication", "1");

        FileSystem fsOp = HDFSClientUtil.getHDFSInstanceByDef(nameNodeUrl, user, conf);

        if (fsOp != null) {

            fsOp.copyFromLocalFile(false,
                    true,
                    new Path("D:\\testarea\\bigdatatest\\hadoop\\hdfs\\wk.txt"),
                    new Path("hdfs://node1:8020/xiyou"));

            RCloseUtil.close(fsOp);
        }
    }


    /**
     * 下载
     * useRawLocalFileSystem   是否开启crc校验:  false(不适用本地文件系统, 意思是必须校验) 开启; true(使用本地落后文件系统, 意思是不校验)  不开启
     * hadoop fs -copyToLocalFile /xxx/xxx.txt  ./
     *
     * crc校验结果  D1 0F 54 93
     * 00000011001000010001110001110011
     * 00000011001000010001110001110011
     *
     *
     * @throws IOException
     */
    @Test
    public void testDownLoadFileFromHDFS() throws IOException {
        Configuration conf = new Configuration();
        conf.set("dfs.replication", "1");

        FileSystem fsOp = HDFSClientUtil.getHDFSInstanceByDef(nameNodeUrl, user, conf);

        /**
         * delSrc  下载后, 是否删除集群上的当前文件
         * src     集群文件位置
         * dst     本地下载地址
         * useRawLocalFileSystem   是否开启crc校验:  false 开启; true  不开启
         */
        if (fsOp != null) {
            fsOp.copyToLocalFile(
                    false,
                    new Path("hdfs://node1:8020/xiyou/hgs/sld/swk.txt"),
                    new Path("D:\\testarea\\bigdatatest\\hadoop\\hdfs"),
                    false);

            RCloseUtil.close(fsOp);
        }
    }


    /**
     * 删除 hadoop fs -rm /xiyou/ts.txt
     *
     * @throws IOException
     */
    @Test
    public void testRmRF() throws IOException {
        Configuration conf = new Configuration();

        FileSystem fsOp = HDFSClientUtil.getHDFSInstanceByDef(nameNodeUrl, user, conf);


        if (fsOp != null) {

            /**
             * pathString  在集群中删除那个文件
             * recursive   是否递归删除
             *
             */
            boolean delete = fsOp.delete(new Path("/xiyou/ts.txt"), false);
            log.info("[**^O^^O^ 删除结果 {} ^O^^O^**]", delete);

            RCloseUtil.close(fsOp);
        }
    }


    /**
     * hadoop fs -mv /xiyou/wk.txt   /xiyou/swk.txt
     * hadoop fs -
     *
     *
     *
     * @throws IOException
     */
    @Test
    public void testMvAndRemove() throws IOException {
        Configuration conf = new Configuration();

        FileSystem fsOp = HDFSClientUtil.getHDFSInstanceByDef(nameNodeUrl, user, conf);


        if (fsOp != null) {

//            boolean rename = fsOp.rename(new Path("/xiyou/swk.txt"), new Path("/xiyou/wk.txt"));
//            log.info("[**^O^^O^ 修改结果 {} ^O^^O^**]", rename);

            // /xiyou/wk.txt   /xiyou/hgs/sld
//            boolean rename1 = fsOp.rename(new Path("/xiyou/wk.txt"), new Path("/xiyou/hgs/sld/swk.txt"));
//            log.info("[**^O^^O^ 移动结果 {} ^O^^O^**]", rename1);

            // /xiyou/psd  ==>  /xiyou/psdyyj
            boolean rename1 = fsOp.rename(new Path("/xiyou/psd"), new Path("/xiyou/psdyyj"));
            log.info("[**^O^^O^ 移动结果 {} ^O^^O^**]", rename1);


            RCloseUtil.close(fsOp);
        }
    }



    // 获取文件详细信息
    @Test
    public void fileDetail() throws IOException {

        Configuration conf = new Configuration();

        FileSystem fsOp = HDFSClientUtil.getHDFSInstanceByDef(nameNodeUrl, user, conf);


        if (fsOp != null) {
            // 获取所有文件信息
            RemoteIterator<LocatedFileStatus> listFiles = fsOp.listFiles(new Path("/"), true);

            // 遍历文件
            while (listFiles.hasNext()) {
                LocatedFileStatus fileStatus = listFiles.next();

                System.out.println("==========" + fileStatus.getPath() + "=========");
                System.out.println(fileStatus.getPermission());
                System.out.println(fileStatus.getOwner());
                System.out.println(fileStatus.getGroup());
                System.out.println(fileStatus.getLen());
                System.out.println(fileStatus.getModificationTime());
                System.out.println(fileStatus.getReplication());
                System.out.println(fileStatus.getBlockSize());
                System.out.println(fileStatus.getPath().getName());

                // 获取块信息
                BlockLocation[] blockLocations = fileStatus.getBlockLocations();

                System.out.println(Arrays.toString(blockLocations));

            }

            RCloseUtil.close(fsOp);
        }

    }



    // 判断是文件夹还是文件
    @Test
    public void testFile() throws IOException {
        Configuration conf = new Configuration();
        FileSystem fsOp = HDFSClientUtil.getHDFSInstanceByDef(nameNodeUrl, user, conf);

        if (null!=fsOp) {
            FileStatus[] listStatus = fsOp.listStatus(new Path("/"));

            for (FileStatus status : listStatus) {

                if (status.isFile()) {
                    System.out.println("文件：" + status.getPath().getName());
                } else {
                    System.out.println("目录：" + status.getPath().getName());
                }
            }

            RCloseUtil.close(fsOp);
        }

    }



}

